package org.gap.jseed.annotation.validation;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

import org.gap.jseed.util.AnnotationExtractor;

public class DomainHandler implements InvocationHandler {
	private Range range;
	private boolean isWithin;
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		if (range == null) {
			Domain domain = AnnotationExtractor.getAnnotation(proxy, method, Domain.class);
			range = new Range(domain.min(), domain.max());
			isWithin = domain.within();
		}
		if (args[0] == null) {
			throw new AssertionError("The value was null");
		}
		
		if (range.contains((Number)args[0]) != isWithin) {
			throw new AssertionError("The value [" + args[0] + "] is not in the range " + range);
		}
		return null;
	}
	/**
	 * Used to determine if a number is contained within the range.
	 *
	 * @author gpelcha
	 */
	public static class Range {
	    public final Double min;
	    public final Double max;

	    public Range(double min, double max) {
	    	this.min = min;
	        this.max = max;
	    }

	    public boolean contains(Number value) {
	        Double number = value.doubleValue();
	        return max >= number && number >= min;
	    }
	    
	    @Override
	    public String toString() {
	    	StringBuffer buffer = new StringBuffer();
	    	if (min == Double.MIN_VALUE) {
	    		buffer.append("(INFINITY, ");
	    	} else {
	    		buffer.append("(" + min + ", ");
	    	}
	    	
	    	if (max == Double.MAX_VALUE) {
	    		buffer.append("INFINITY)");
	    	} else {
	    		buffer.append(max + ")");
	    	}
	    	return buffer.toString();
	    }
	}
}
